import React, { Component } from 'react';
// eslint-disable-next-line import/no-unresolved
import Scrollbar from 'react-scrollbars-custom';
import { connect } from 'dva';
import { formatMessage } from 'umi-plugin-react/locale';
import router from 'umi/router';
import { Link } from 'umi';
import { Icon } from 'antd';
import classNames from 'classnames';
import dropByCacheKey from 'umi/dropByCacheKey';
import getCachingKeys from 'umi/getCachingKeys';
import { StateType } from '@/common-typings';
import { ConnectProps } from '@/models/connect';
import Observer from '@/utils/observer';
import styles from './TagView.less';

export interface GlobalTagViewProps extends ConnectProps {
  cachedViews: [];
  curVisitedPath: any;
  location: any;
}

class TagView extends Component<GlobalTagViewProps> {
  public state = {
    visible: false,
    top: 0,
    left: 0,
    selectedTag: {},
  };

  // eslint-disable-next-line react/sort-comp
  UNSAFE_componentWillReceiveProps(nextProps: any) {
    if (
      !this.props.cachedViews.length ||
      (this.props.location && nextProps.location.pathname !== this.props.location.pathname)
    ) {
      this.changeTagViewState(nextProps);
    }
  }

  // eslint-disable-next-line react/sort-comp
  UNSAFE_componentWillUpdate(nextProps: any, nextState: any) {
    if (nextState.visible) {
      document.body.addEventListener('click', this.closeMenu);
    } else {
      document.body.removeEventListener('click', this.closeMenu);
    }
  }

  componentWillUnmount() {
    document.body.removeEventListener('click', this.closeMenu);
  }

  isActive = (route: any) => {
    const { location } = this.props;
    return route.path === location.pathname;
  };

  // 关闭菜单
  closeMenu = (e: any) => {
    const idList = ['closeSelectedTag', 'closeOthersTags', 'closeAllTags'];
    this.setState({ visible: false });
    if (e.target && e.target.id && idList.includes(e.target.id)) {
      if (e.target.id === 'closeSelectedTag') {
        this[e.target.id](e, this.state.selectedTag);
      } else {
        this[e.target.id](e);
      }
    }
  };

  // 监听路由变化，更新redux
  changeTagViewState = (prop: StateType) => {
    const { location, menuData, dispatch } = prop;
    let result = {};

    // 获取当前访问的路由明细
    const getCurPathData = (menuDatas: StateType) => {
      menuDatas.map((item: StateType) => {
        if (item.path === location.pathname) {
          result = {
            ...item,
            names: formatMessage({ id: item.locale, defaultMessage: item.locale }),
          };
        } else if (item.children && !!item.children.length && !result.hasOwnProperty('path')) {
          return getCurPathData(item.children);
        }
        return item;
      });
    };
    getCurPathData(menuData);

    if (result.hasOwnProperty('path') && !!dispatch) {
      dispatch({
        type: 'tagView/addAccessViews',
        payload: result,
      });
      dispatch({
        type: 'tagView/changeCurAccessPath',
        payload: result,
      });
    }
  };

  // 点击关闭按钮
  closeSelectedTag(e: any, tag: any) {
    e.preventDefault();
    e.stopPropagation();
    const { dispatch, cachedViews } = this.props;
    if (dispatch) {
      dispatch({
        type: 'tagView/delAccessViews',
        payload: tag,
        callback: () => {
          if (this.isActive(tag)) {
            const newCachedView = cachedViews.filter((i: any) => i.path !== tag.path);
            const latestView: any = newCachedView.slice(-1)[0];
            if (latestView) {
              router.push(latestView.path);
            } else {
              router.push('/');
            }
          }
          // 清理路由缓存
          dropByCacheKey(tag.path);
        },
      });
    }
  }

  // 打开菜单栏
  openMenu(e: any, tag: any) {
    e.preventDefault();
    e.stopPropagation();
    this.setState({
      visible: true,
      selectedTag: tag,
      left: e.clientX,
      top: e.clientY,
    });
  }

  /**
   * 关闭其他，由于mui路由机制不同，会遍历变化的menuData
   * 在遍历的item中去判别是否已经缓存，如果清理父级的缓存key，cacheRoute会认为是一个新的组件，则子集都不能实现缓存
   * @param e
   */
  closeOthersTags(e: any) {
    e.preventDefault();
    const { dispatch, cachedViews } = this.props;
    const { selectedTag }: any = this.state;
    if (dispatch) {
      // 获取redux缓存的路由
      const cacheList: string[] = [];
      cachedViews.map((i: StateType) => {
        cacheList.push(i.pathname);
        return i;
      });
      // 删除除选中外的其他tag
      dispatch({
        type: 'tagView/delOtherView',
        payload: selectedTag,
      });
      // 重置当前selectTag
      dispatch({
        type: 'tagView/changeCurAccessPath',
        payload: selectedTag,
      });
      const pathList = getCachingKeys();
      pathList.forEach((path: string) => {
        // 当不为selectTag并且在redux中有存储的进行clear
        if (path !== selectedTag.path && cacheList.includes(path)) {
          dropByCacheKey(path);
        }
      });
    }
  }

  // 关闭所有
  closeAllTags(e: any) {
    e.preventDefault();
    const { dispatch } = this.props;
    if (dispatch) {
      dispatch({
        type: 'tagView/delAllViews',
        payload: this.state.selectedTag,
        callback: () => {
          router.push('/');
        },
      });
      const pathList = getCachingKeys();
      pathList.map((path: string) => {
        dropByCacheKey(path);
        return path;
      });
    }
  }

  // 点击tag
  clickTag(e: any, item: any) {
    if (e.target.nodeName === 'A') {
      Observer.trigger('saveBtnsData', item.path);
    } else {
      this.closeSelectedTag(e, item);
    }
  }

  render(): any {
    const { cachedViews, curVisitedPath } = this.props;
    const { visible, top, left } = this.state;
    return (
      <div className={styles['tags-view-container']}>
        <Scrollbar style={{ height: '44px' }} noScrollY>
          <div style={{ height: '36px', whiteSpace: 'nowrap' }}>
            {cachedViews.map((item: any) => (
              <Link
                className={classNames(
                  styles['tags-view-item'],
                  curVisitedPath.path === item.path ? styles.active : '',
                )}
                to={item.path}
                key={item.path}
                onClick={e => this.clickTag(e, item)}
                onContextMenu={(e: any) => this.openMenu(e, item)}
              >
                {item.names}
                <Icon
                  type="close"
                  className={styles['close-icon']}
                  // onClick={e => this.closeSelectedTag(e, item)}
                />
              </Link>
            ))}
          </div>
        </Scrollbar>
        {visible && (
          <ul className={styles.contextmenu} style={{ left: `${left}px`, top: `${top}px` }}>
            <li id="closeSelectedTag">关闭</li>
            <li id="closeOthersTags">关闭其他</li>
            <li id="closeAllTags">关闭所有</li>
          </ul>
        )}
      </div>
    );
  }
}

export default connect(({ tagView }: { tagView: any }) => tagView)(TagView);
